#ifndef _VISROCE_VERBS_H
#define _VISROCE_VERBS_H

#include <infiniband/verbs.h>

struct ibv_device **visroce_get_device_list(int *num_devices);
/**
 * visroce_free_device_list - Free list from visroce_get_device_list()
 * Free an array of devices returned from visroce_get_device_list().  Once
 * the array is freed, pointers to devices that were not opened with
 * visroce_open_device() are no longer valid.  Client code must open all
 * devices it intends to use before calling visroce_free_device_list().
 */
void visroce_free_device_list(struct ibv_device **list);

/**
 * visroce_get_device_name - Return kernel device name
 */
const char *visroce_get_device_name(struct ibv_device *device);

/**
 * visroce_get_device_guid - Return device's node GUID
 */
__be64 visroce_get_device_guid(struct ibv_device *device);

/**
 * visroce_open_device - Initialize device for use
 */
struct ibv_context *visroce_open_device(struct ibv_device *device);

/**
 * visroce_close_device - Release device
 */
int visroce_close_device(struct ibv_context *context);

/**
 * visroce_node_type_str - Return string describing node_type enum value
 */
const char *visroce_node_type_str(enum ibv_node_type node_type);

/**
 * visroce_port_state_str - Return string describing port_state enum value
 */
const char *visroce_port_state_str(enum ibv_port_state port_state);

/**
 * visroce_query_device - Get device properties
 */
int visroce_query_device(struct ibv_context *context,
    struct ibv_device_attr *device_attr);

/**
 * visroce_query_port - Get port properties
 */
int visroce_query_port(struct ibv_context *context,
    uint8_t port_num, struct ibv_port_attr *port_attr);

/**
 * visroce_query_gid - Get a GID table entry
 */
int visroce_query_gid(struct ibv_context *context,
    uint8_t port_num, int index, union ibv_gid *gid);

/**
 * visroce_query_pkey - Get a P_Key table entry
 */
int visroce_query_pkey(struct ibv_context *context, uint8_t port_num,
    int index, __be16 *pkey);

/**
 * visroce_alloc_pd - Allocate a protection domain
 */
struct ibv_pd *visroce_alloc_pd(struct ibv_context *context);

/**
 * visroce_dealloc_pd - Free a protection domain
 */
int visroce_dealloc_pd(struct ibv_pd *pd);

/**
 * visroce_create_cq - Create a completion queue
 * @context - Context CQ will be attached to
 * @cqe - Minimum number of entries required for CQ
 * @cq_context - Consumer-supplied context returned for completion events
 * @channel - Completion channel where completion events will be queued.
 *     May be NULL if completion events will not be used.
 * @comp_vector - Completion vector used to signal completion events.
 *     Must be >= 0 and < context->num_comp_vectors.
 */
struct ibv_cq *visroce_create_cq(struct ibv_context *context,
    int cqe, void *cq_context,
    struct ibv_comp_channel *channel, int comp_vector);

/**
 * visroce_resize_cq - Modifies the capacity of the CQ.
 * @cq: The CQ to resize.
 * @cqe: The minimum size of the CQ.
 * Users can examine the cq structure to determine the actual CQ size.
 */
int visroce_resize_cq(struct ibv_cq *cq, int cqe);

/**
 * visroce_destroy_cq - Destroy a completion queue
 */
int visroce_destroy_cq(struct ibv_cq *cq);

/**
 * visroce_create_comp_channel - Create a completion event channel
 */
struct ibv_comp_channel *visroce_create_comp_channel(struct ibv_context *context);

/**
 * visroce_destroy_comp_channel - Destroy a completion event channel
 */
int visroce_destroy_comp_channel(struct ibv_comp_channel *channel);

/**
 * visroce_reg_mr - Register a memory region
 */
struct ibv_mr *visroce_reg_mr(struct ibv_pd *pd, void *addr,
    size_t length, int access);

/**
 * visroce_dereg_mr - Deregister a memory region
 */
int visroce_dereg_mr(struct ibv_mr *mr);

/**
 * visroce_create_qp - Create a queue pair.
 */
struct ibv_qp *visroce_create_qp(struct ibv_pd *pd,
    struct ibv_qp_init_attr *qp_init_attr);

/**
 * visroce_destroy_qp - Destroy a queue pair.
 */
int visroce_destroy_qp(struct ibv_qp *qp);

/**
 * visroce_create_srq - Creates a SRQ associated with the specified protection
 *   domain.
 * @pd: The protection domain associated with the SRQ.
 * @srq_init_attr: A list of initial attributes required to create the SRQ.
 * srq_attr->max_wr and srq_attr->max_sge are read the determine the
 * requested size of the SRQ, and set to the actual values allocated
 * on return.  If visroce_create_srq() succeeds, then max_wr and max_sge
 * will always be at least as large as the requested values.
 */
struct ibv_srq *visroce_create_srq(struct ibv_pd *pd,
    struct ibv_srq_init_attr *srq_init_attr);

/**
 * visroce_destroy_srq - Destroys the specified SRQ.
 * @srq: The SRQ to destroy.
 */
int visroce_destroy_srq(struct ibv_srq *srq);

/**
 * visroce_create_ah - Create an address handle.
 */
struct ibv_ah *visroce_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr);

/**
 * visroce_destroy_ah - Destroy an address handle.
 */
int visroce_destroy_ah(struct ibv_ah *ah);

/**
 * visroce_modify_qp - Modify a queue pair.
 */
int visroce_modify_qp(struct ibv_qp *qp,
    struct ibv_qp_attr *attr, int attr_mask);

/**
 * visroce_query_qp - Returns the attribute list and current values for the
 *   specified QP.
 * @qp: The QP to query.
 * @attr: The attributes of the specified QP.
 * @attr_mask: A bit-mask used to select specific attributes to query.
 * @init_attr: Additional attributes of the selected QP.
 * The qp_attr_mask may be used to limit the query to gathering only the
 * selected attributes.
 */
int visroce_query_qp(struct ibv_qp *qp,
    struct ibv_qp_attr *attr, int attr_mask,
    struct ibv_qp_init_attr *init_attr);

/**
 * visroce_query_srq - Returns the attribute list and current values for the
 *   specified SRQ.
 * @srq: The SRQ to query.
 * @srq_attr: The attributes of the specified SRQ.
 */
int visroce_query_srq(struct ibv_srq *srq, struct ibv_srq_attr *srq_attr);

/**
 * visroce_post_recv - Post a list of work requests to a receive queue.
 */
int visroce_post_recv(struct ibv_qp *qp,
    struct ibv_recv_wr *wr, struct ibv_recv_wr **bad_wr);

/**
 * visroce_post_send - Post a list of work requests to a send queue.
 * If IBV_SEND_INLINE flag is set, the data buffers can be reused
 * immediately after the call returns.
 */
int visroce_post_send(struct ibv_qp *qp,
    struct ibv_send_wr *wr, struct ibv_send_wr **bad_wr);

/**
 * visroce_post_srq_recv - Posts a list of work requests to the specified SRQ.
 * @srq: The SRQ to post the work request on.
 * @recv_wr: A list of work requests to post on the receive queue.
 * @bad_recv_wr: On an immediate failure, this parameter will reference
 *   the work request that failed to be posted on the QP.
 */
int visroce_post_srq_recv(struct ibv_srq *srq,
    struct ibv_recv_wr *recv_wr, struct ibv_recv_wr **bad_recv_wr);

/**
 * visroce_req_notify_cq - Request completion notification on a CQ.  An
 *   event will be added to the completion channel associated with the
 *   CQ when an entry is added to the CQ.
 * @cq: The completion queue to request notification for.
 * @solicited_only: If non-zero, an event will be generated only for
 *   the next solicited CQ entry.  If zero, any CQ entry, solicited or
 *   not, will generate an event.
 */
int visroce_req_notify_cq(struct ibv_cq *cq, int solicited_only);

/**
 * visroce_get_cq_event - Read next CQ event
 * @channel: Channel to get next event from.
 * @cq: Used to return pointer to CQ.
 * @cq_context: Used to return consumer-supplied CQ context.
 * All completion events returned by visroce_get_cq_event() must
 * eventually be acknowledged with visroce_ack_cq_events().
 */
int visroce_get_cq_event(struct ibv_comp_channel *channel,
    struct ibv_cq **cq, void **cq_context);

/**
 * visroce_ack_cq_events - Acknowledge CQ completion events
 * @cq: CQ to acknowledge events for
 * @nevents: Number of events to acknowledge.
 * All completion events which are returned by visroce_get_cq_event() must
 * be acknowledged.  To avoid races, visroce_destroy_cq() will wait for
 * all completion events to be acknowledged, so there should be a
 * one-to-one correspondence between acks and successful gets.  An
 * application may accumulate multiple completion events and
 * acknowledge them in a single call to visroce_ack_cq_events() by passing
 * the number of events to ack in @nevents.
 */
void visroce_ack_cq_events(struct ibv_cq *cq, unsigned int nevents);

/**
 * visroce_poll_cq - Poll a CQ for work completions
 * @cq:the CQ being polled
 * @num_entries:maximum number of completions to return
 * @wc:array of at least @num_entries of &struct ibv_wc where completions
 *   will be returned
 * Poll a CQ for (possibly multiple) completions.  If the return value
 * is < 0, an error occurred.  If the return value is >= 0, it is the
 * number of completions returned.  If the return value is
 * non-negative and strictly less than num_entries, then the CQ was
 * emptied.
 */
int visroce_poll_cq(struct ibv_cq *cq, int num_entries, struct ibv_wc *wc);

/**
 * visroce_init_ah_from_wc - Initializes address handle attributes from a
 *   work completion.
 * @context: Device context on which the received message arrived.
 * @port_num: Port on which the received message arrived.
 * @wc: Work completion associated with the received message.
 * @grh: References the received global route header.  This parameter is
 *   ignored unless the work completion indicates that the GRH is valid.
 * @ah_attr: Returned attributes that can be used when creating an address
 *   handle for replying to the message.
 */
int visroce_init_ah_from_wc(struct ibv_context *context, uint8_t port_num,
    struct ibv_wc *wc, struct ibv_grh *grh, struct ibv_ah_attr *ah_attr);

/**
 * visroce_create_ah_from_wc - Creates an address handle associated with the
 *   sender of the specified work completion.
 * @pd: The protection domain associated with the address handle.
 * @wc: Work completion information associated with a received message.
 * @grh: References the received global route header.  This parameter is
 * ignored unless the work completion indicates that the GRH is valid.
 * @port_num: The outbound port number to associate with the address.
 * The address handle is used to reference a local or global destination
 * in all UD QP post sends.
 */
struct ibv_ah *visroce_create_ah_from_wc(struct ibv_pd *pd, struct ibv_wc *wc,
    struct ibv_grh *grh, uint8_t port_num);

/**
 * visroce_attach_mcast - Attaches the specified QP to a multicast group.
 * @qp: QP to attach to the multicast group.  The QP must be a UD QP.
 * @gid: Multicast group GID.
 * @lid: Multicast group LID in host byte order.
 * In order to route multicast packets correctly, subnet
 * administration must have created the multicast group and configured
 * the fabric appropriately.  The port associated with the specified
 * QP must also be a member of the multicast group.
 */
int visroce_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid);

/**
 * visroce_detach_mcast - Detaches the specified QP from a multicast group.
 * @qp: QP to detach from the multicast group.
 * @gid: Multicast group GID.
 * @lid: Multicast group LID in host byte order.
 */
int visroce_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid);

/**
 * visroce_get_async_event - Get next async event
 * @event: Pointer to use to return async event
 * All async events returned by visroce_get_async_event() must eventually
 * be acknowledged with visroce_ack_async_event().
 */
int visroce_get_async_event(struct ibv_context *context,
    struct ibv_async_event *event);

/**
 * visroce_ack_async_event - Acknowledge an async event
 * @event: Event to be acknowledged.
 * All async events which are returned by visroce_get_async_event() must
 * be acknowledged.  To avoid races, destroying an object (CQ, SRQ or
 * QP) will wait for all affiliated events to be acknowledged, so
 * there should be a one-to-one correspondence between acks and
 * successful gets.
 */
void visroce_ack_async_event(struct ibv_async_event *event);

/**
 * visroce_event_type_str - Return string describing event_type enum value
 */
const char *visroce_event_type_str(enum ibv_event_type event);
struct ibv_wc *visroce_alloc_ibv_wc(struct ibv_qp *qp, int cnt);
int visroce_hw_ec_switch(int ec_switch);
int visroce_hw_flow_switch(int flow_switch);
#endif /* _VISROCE_VERBS_H */